package com.tlgen.coopera.service.impl;

import com.tlgen.coopera.service.HeartBeatService;
import com.tlgen.coopera.utils.HttpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

/*
 *@title HeartBeatServiceImpl
 *@description
 *@author ta151486
 *@version 1.0
 *@create 2023/12/13 15:14
 */
@Service
public class HeartBeatServiceImpl implements HeartBeatService {

    @Autowired
    private Environment environment;

    @Override
    public void receive() {
        // 接收 udp 心跳
        try {
            String port = Optional.ofNullable(environment.getProperty("server.port")).orElse("8080");
            DatagramSocket socket = new DatagramSocket(Integer.parseInt(port)); // 创建监听 UDP 数据的socket，并绑定端口号
            byte[] buffer = new byte[1024]; // 创建缓冲区用于存储接收到的数据
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length); // 创建数据包用于接收UDP数据
            while (true) {
                socket.receive(packet); // 接收 UDP 数据，此方法会阻塞直到接收到数据为止
                String receivedData = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.UTF_8); // 从数据包中获取接收到的数据
                System.out.println("接收到来自注册中心的心跳检测");
                System.out.println(receivedData);
                String[] split = receivedData.split(":"); // beat:192.168.1.5:9994
                // 构造 ACK 确认消息
                String ackMessage = "ACK:" + HttpUtils.selectLocalIp() + ":" + port;
                byte[] ackData = ackMessage.getBytes(StandardCharsets.UTF_8);
                // 设置 ACK 确认消息的源地址、端口等属性
                InetAddress sourceAddress = InetAddress.getByName(split[1]);
                int sourcePort = Integer.parseInt(split[2]);
                // 创建 ACK 确认数据包
                DatagramPacket ackPacket = new DatagramPacket(ackData, ackData.length, sourceAddress, sourcePort);
                // 发送 ACK 确认消息
                socket.send(ackPacket);
                System.out.println("接收到来自注册中心的心跳检测 === 已回复 ACK 确认");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
